In the previous challenge ([[1a. Create options page and save options with storage API]]), we have an options page. User ticks a checkbox. That checkbox remains ticked the next time the user opens the Options page. But so what? There are no real consequences other than persisting the option on the option page. In this tutorial, we'll see what happens when other parts of the Chrome extension taps into the Storage API's storage that got modified by the Options page. Let's make a chrome extension that changes all webpage's background colors (well, most websites) ## Setup Create icon files set. You should know how by now. Create manifest.json: ``` { "manifest_version": 3, "name": "", "version": "1.0", "description": ".", "author": "Weng Fei Fung", "icons": { "16": "icon16x16.png", "32": "icon32x32.png", "48": "icon48x48.png", "128": "icon128x128.png" }, "content_security_policy": { "extension_pages": "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; object-src 'self';" }, "host_permissions": [ "https://*/*", "http://*/*" ], "content_scripts": [ { "matches": ["https://*/*", "http://*/*"], "js": ["content.js"], "run_at": "document_end" } ], "permissions": [ "storage", "tabs", "activeTab" ], "options_ui": { "page": "options.html", "open_in_tab": false } } ``` ^ We are combining content scripts with options and storage Create `options.html` to have dropdown of background colors to choose from: ``` Options

Options

Change the background color of all websites

``` Create `options.js` to save to Storage API when the user selects a background color (and close the Options Page when user clicks the Close button): ``` // Get the checkbox element const bgcolorDropdown = document.getElementById('color-select'); // Load saved checkbox state when the page loads document.addEventListener('DOMContentLoaded', async () => { const result = await chrome.storage.local.get(['backgroundColor']); document.getElementById('color-select').value = result.backgroundColor || 'inherit'; console.log("DOMContentLoaded:Background color set to:", document.getElementById('color-select').value); }); // Save checkbox state when it changes bgcolorDropdown.addEventListener('change', async () => { await chrome.storage.local.set({ backgroundColor: document.getElementById('color-select').value }); console.log("onChange: Background color set to:", document.getElementById('color-select').value); }); // Close the options page document.getElementById('btn-close').addEventListener('click', async () => { window.close(); }); ``` Create `options.css` to make the Options page look nice: ``` body { width: 550px; height: 300px; padding: 10px; } h1 { font-size: 20px; margin-bottom: 20px; } footer { position: absolute; bottom: 20px; right: 20px; text-align: right; } ``` Finally, we create `content.js` to load on all webpages (due to manifest.json broadly wildcard matching all possible domains for content_scripts), checking if we have a background color saved to Storage API: And if we have a background color from Storage API, set the background color of the web content to that background color: ``` console.log("Content script loaded"); async function applyBackgroundColor() { try { const result = await chrome.storage.local.get(['backgroundColor']); console.log("chrome.storage.local.get:Background color loaded was: ", result.backgroundColor); if (result && result.backgroundColor && result.backgroundColor !== 'inherit') { // Change background color of the body document.body.style.backgroundColor = result.backgroundColor; // Change background color of all elements (in case they have their own background color rules and not let body's background color to bleed through) document.querySelectorAll("html, body, div, span, header, main, footer, nav, aside, section, article").forEach(el=>{ el.style.backgroundColor = result.backgroundColor; }); console.log("Background color set to: ", result.backgroundColor); } else { console.log("Background color inherits"); } } catch (error) { console.error("Error applying background color:", error); } } applyBackgroundColor(); ``` ## Testing Install the chrome extension code. Open options (You can right click the extension icon -> Options). Then select blue for background color. Visit google.com: ![[Pasted image 20250405031456.png]] Visit ask.com: ![[Pasted image 20250405031517.png]] Caveats: This doesn't work for websites whose layout are rendered with a JS framework and then the div's rendered a split second later have their own background colors that blocks body's background color from bleeding through. - duckduckgo.com is such a website. They use a JS framework for rendering and for a split second the body had no elements. The div elements they render have background colors: ![[Pasted image 20250405031600.png]] Keep in mind that websites can change styles. The above statements are true as of 4/5/2025. Theoretically, this can be solved by adding a delay before the background colors are applied (using setTimeout). But that is neither here nor there because you are just testing the chrome extension with the webpage opened to google.com. This concludes the tutorial. You may want to uninstall the chrome extension at chrome://extensions so you don't get a coloring headache with your web surfing experience later.